﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.InteropServices;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Media.Media3D;
using System.Windows.Shapes;

using Aliphant.Common;
using Aliphant.UI.Models;
using Aliphant.UI.Windows;

namespace Aliphant.UI
{
    /// <summary>
    /// Widget.xaml 的交互逻辑
    /// </summary>
    public partial class Widget : UIWindow
    {
        public event Action? CloseEventHandler;
        public bool IsClosed = false;
        public double RightMargin = 1870;

        private bool IsAdsorption = false;   // 开启吸附
        private bool _winBarVisible = true;
        private double ScreenWidth = 0;
        private double ScreenHeight = 0;
        private WindowLocationStyle _location = WindowLocationStyle.Normal;
        private bool _isInWindow = false;
        private double borderWidth = 2;
        Regex regex = new Regex(@"^[a-z,0-9]$", RegexOptions.IgnoreCase);
        double l_bottom = 0;
        double l_right = 0;
        bool isKeyDown = false;

        public Widget(IWidget main)
        {
            InitializeComponent();
            Loading(main);
        }

        public Widget(IWidget main, bool winBar)
        {
            InitializeComponent();
            WinBarVisible = winBar;
            Loading(main);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="main"></param>
        /// <param name="winBar">是否显示窗口边框</param>
        /// <param name="isAdsorption">是否贴边吸附</param>
        public Widget(IWidget main, bool winBar, bool isAdsorption)
        {
            InitializeComponent();
            WinBarVisible = winBar;
            IsAdsorption = isAdsorption;
            Loading(main);
        }

        public Widget(IWidget main, string script)
        {
            InitializeComponent();
            WinBarVisible = false;
            IsAdsorption = false;
            main.SetScriptPath(script);
            Loading(main);
        }

        public double Right
        {
            get => ScreenWidth - this.Left - this.ActualWidth;
            set
            {
                this.Left = ScreenWidth - value - this.ActualWidth;
            }
        }

        public double Bottom
        {
            get => ScreenHeight - this.Top - this.ActualHeight;
            set
            {
                this.Top = ScreenHeight - value - this.ActualHeight;
            }
        }


        public bool WinBarVisible
        {
            get => _winBarVisible;
            set
            {
                _winBarVisible = value;
                winBar.Visibility = value ? Visibility.Visible : Visibility.Collapsed;
            }
        }

        /// <summary>
        /// 注册按钮
        /// </summary>
        /// <param name="btnNum"></param>
        /// <param name="action"></param>
        public void RegistAction(int btnNum, string? tip, Geometry? data, Action? action)
        {
            Button? btn = null;
            Path? path = null;

            switch (btnNum)
            {
                case 0:
                    btn = btn1;
                    path = btn1Icon;
                    break;
                case 1:
                    btn = btn2;
                    path = btn2Icon;
                    break;
            }

            if (btn == null || path == null)
            {
                return;
            }

            path.Data = data;

            btn.ToolTip = tip;
            btn.Click += (s, e) =>
            {
                action?.Invoke();
            };
            btn.Visibility = Visibility.Visible;

            // 添加到右击菜单
            if (!WinBarVisible)
            {
                MenuItem menuItem = new MenuItem();
                menuItem.Header = tip;
                menuItem.Click += (s, e) =>
                {
                    action?.Invoke();
                };
                menuItem.Style = (Style)this.FindResource("FIconMenuItem");
                menus.Items.Insert(0, menuItem);
            }
        }

        /// <summary>
        /// 注册按钮
        /// </summary>
        /// <param name="btnNum"></param>
        /// <param name="icon"></param>
        /// <param name="action"></param>
        public void RegistAction(int btnNum, string? tip, string? icon, Action? action)
        {
            if (string.IsNullOrEmpty(icon) || action == null)
            {
                return;
            }

            Geometry? data = Application.Current.FindResource(icon) as Geometry;
            RegistAction(btnNum, tip, data, action);
        }

        /// <summary>
        /// 拖动窗口
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void DropWindow(object sender, MouseButtonEventArgs e)
        {
            // 判断是否点击的是菜单区域
            bool isClickOnBlankArea = e.OriginalSource is Border border && border.Name == "winBar";

            // 通过 InputManager 主动触发命令
            if (isClickOnBlankArea)
            {
                // 直接调用这个命令就可以实现拖动啦，嘻嘻
                GlobalProperty.WindowDropMoveCommand.Execute(null, null);
            }

            if (!IsAdsorption)
            {
                return;
            }

            Logger.Info("Check");
            if (Right <= 0)
            {
                this.Left = ScreenWidth - borderWidth;
                _location = WindowLocationStyle.Hide;
            }
            else if (Left <= 0)
            {
                this.Right = ScreenWidth - borderWidth;
                _location = WindowLocationStyle.Hide;
            }
            else if (Top <= 0)
            {
                this.Bottom = ScreenHeight - borderWidth;
                _location = WindowLocationStyle.Hide;
            }
            else if (Bottom <= 0)
            {
                this.Top = ScreenHeight - borderWidth;
                _location = WindowLocationStyle.Hide;
            }
            else
            {
                _location = WindowLocationStyle.Normal;
            }

        }

        private void DropWindowOver(object sender, MouseButtonEventArgs e)
        {

        }


        private void CloseWnd(object sender, RoutedEventArgs e)
        {
            this.Close();
        }

        protected override void OnClosing(CancelEventArgs e)
        {
            base.OnClosing(e);
            IsClosed = true;
            CloseEventHandler?.Invoke();
        }

        private void HideWnd(object sender, RoutedEventArgs e)
        {
            this.Hide();
        }

        private void Exit(object sender, RoutedEventArgs e)
        {
            this.Close();
        }

        private void Loading(IWidget main)
        {
            main.Init(this);

            CloseEventHandler += main.Close;
            RegistAction(0, main.QuickButton1Tip, main.QucikButton1Icon, main.QuickAction1);
            RegistAction(1, main.QuickButton2Tip, main.QucikButton2Icon, main.QuickAction2);
            this.comptMain.Content = main;

            ScreenWidth = SystemParameters.VirtualScreenWidth;
            ScreenHeight = SystemParameters.VirtualScreenHeight;

            if (IsAdsorption)
            {
                body.Padding = new Thickness(borderWidth, 0, borderWidth, borderWidth);
                body.Background = new SolidColorBrush(Color.FromArgb(10, 255, 255, 255));
            }

        }

        private void DockPanel_MouseEnter(object sender, MouseEventArgs e)
        {
            if (!IsAdsorption)
            {
                return;
            }

            try
            {
                if (_location != WindowLocationStyle.Hide)
                {
                    return;
                }

                if (this.Left == ScreenWidth - borderWidth)
                {
                    this.Right = 0;
                }
                else if (this.Right == ScreenWidth - borderWidth)
                {
                    this.Left = 0;
                }
                else if (this.Bottom == ScreenHeight - borderWidth)
                {
                    this.Top = 0;
                }
                else if (this.Top == ScreenHeight - borderWidth)
                {
                    this.Bottom = 0;
                }
                _isInWindow = true;
                _location = WindowLocationStyle.Over;
            }
            catch (Exception ex)
            {
                Logger.Error(ex);
            }
        }

        private void DockPanel_MouseLeave(object sender, MouseEventArgs e)
        {
            //Logger.Info("MouseLeave");
            if (!IsAdsorption)
            {
                return;
            }

            try
            {
                DoGetCursorPos(out Aliphant.Datas.Point point);

                //Logger.Info($"Point: X:{point.X}, Y:{point.Y}");
                //Logger.Info($"Window: Left:{Left}, Right:{Left + this.ActualWidth}, Top:{Top}, Bottom:{Top + ActualHeight}");

                if (point.X > Left && point.X < (Left + this.ActualWidth) && point.Y > Top && point.Y < (Top + ActualHeight))
                {
                    _isInWindow = true;
                }
                else
                {
                    _isInWindow = false;
                }

                if (_location != WindowLocationStyle.Over || _isInWindow)
                {
                    return;
                }

                if (this.Right == 0)
                {
                    this.Left = ScreenWidth - borderWidth;
                }
                else if (this.Left == 0)
                {
                    this.Right = ScreenWidth - borderWidth;
                }
                else if (this.Top == 0)
                {
                    this.Bottom = ScreenHeight - borderWidth;
                }
                else if (this.Bottom <= 0)
                {
                    this.Top = ScreenHeight - borderWidth;
                }
                _location = WindowLocationStyle.Hide;
            }
            catch (Exception ex)
            {
                Logger.Error(ex);
            }
        }



        [DllImport("user32.dll")]
        public static extern IntPtr GetCursorPos(out Aliphant.Datas.Point lpPoint);

        private void DoGetCursorPos(out Aliphant.Datas.Point point)
        {
            IntPtr result = GetCursorPos(out Aliphant.Datas.Point tagPOINT);
            if (result.ToInt32() == 1)
            {
                point = tagPOINT;
            }
            else
            {
                point = new Aliphant.Datas.Point();
            }
        }

        private void Window_KeyDown(object sender, KeyEventArgs e)
        {
            if (!IsAdsorption)
            {
                return;
            }

            if (_location != WindowLocationStyle.Hide)
            {
                return;
            }

            var key = e.Key.ToString();
            if (regex.IsMatch(key) || e.Key == Key.CapsLock)
            {
                if (!isKeyDown)
                {
                    l_bottom = Bottom;
                    l_right = Right;

                    Bottom = 0;
                    Right = RightMargin + 10;
                    isKeyDown = true;
                }
            }
        }

        private void Window_KeyUp(object sender, KeyEventArgs e)
        {
            if (!IsAdsorption)
            {
                return;
            }

            var key = e.Key.ToString();
            if (regex.IsMatch(key) || e.Key == Key.CapsLock)
            {
                Time.Tick();
                if (isKeyDown && Time.deltaTime > 0.2f)
                {
                    Bottom = l_bottom;
                    Right = l_right;

                    isKeyDown = false;
                }
            }
        }

        private void TopUp(object sender, RoutedEventArgs e)
        {
            if (this.Topmost == true)
            {
                this.Topmost = false;
            }
            else
            {
                this.Topmost = true;
            }
        }
    }
}
